﻿using FileToVideo.Config;
using FileToVideo.Enums;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Range = OpenCvSharp.Range;

namespace FileToVideo.AddFunc
{
    /// <summary>
    /// Mat追加方法
    /// </summary>
    public static class MatAdd
    {
        /// <summary>
        /// 从 Mat 中读取数据并还原为原始字符串（使用平均颜色）
        /// </summary>
        public static string ConvertMat2StringWithAverage(this Mat mat, PartSizeMode_1080P partSize, Dictionary<char, Color> keyColors)
        {
            if (mat == null || mat.Empty())
                return string.Empty;

            if (keyColors.Count == 0)
            {
                throw new Exception($"未传入的密钥字典!");
            }

            Dictionary<Color, char> colorToCharMap = new Dictionary<Color, char>();
            foreach (var kvp in keyColors)
            {
                colorToCharMap[kvp.Value] = kvp.Key;
            }

            var partSizeValue = (int)partSize;
            int row = Setting.width / partSizeValue;
            int col = Setting.height / partSizeValue;

            StringBuilder resultBuilder = new StringBuilder(row * col);

            for (int i = 0; i < row; i++)
            {
                for (int j = 0; j < col; j++)
                {
                    int startX = i * partSizeValue;
                    int endX = (i + 1) * partSizeValue;
                    int startY = j * partSizeValue;
                    int endY = (j + 1) * partSizeValue;

                    Mat block = mat[new Range(startY, endY), new Range(startX, endX)];

                    // 计算色块的平均颜色
                    Scalar meanScalar = Cv2.Mean(block);
                    Color averageColor = Color.FromArgb(
                        255,
                        (int)meanScalar.Val2, // R
                        (int)meanScalar.Val1, // G  
                        (int)meanScalar.Val0  // B
                    );

                    // 检查是否为透明色，如果是则立即结束
                    if (averageColor.A == 0 || IsTransparentColor(averageColor))
                    {
                        return resultBuilder.ToString();
                    }

                    char character = ' ';
                    if (colorToCharMap.ContainsKey(averageColor))
                    {
                        character = colorToCharMap[averageColor];
                    }
                    else
                    {
                        character = FindClosestColorCharacter(averageColor, colorToCharMap);
                    }

                    resultBuilder.Append(character);
                }
            }

            return resultBuilder.ToString();
        }

        /// <summary>
        /// 从 Mat 中读取数据并还原为原始字符串 (使用中心点颜色)
        /// </summary>
        /// <param name="mat"></param>
        /// <param name="partSize"></param>
        /// <param name="keyColors"></param>
        /// <returns></returns>
        public static string ConvertMat2String(this Mat mat, PartSizeMode_1080P partSize,Dictionary<char, Color> keyColors)
        {
            if (mat == null || mat.Empty())
                return string.Empty;

            if (keyColors.Count == 0)
            {
                throw new Exception($"未传入的密钥字典!");
            }

            Dictionary<Color, char> colorToCharMap = new Dictionary<Color, char>();
            foreach (var kvp in keyColors)
            {
                colorToCharMap[kvp.Value] = kvp.Key;
            }

            var partSizeValue = (int)partSize;
            int row = Setting.width / partSizeValue;
            int col = Setting.height / partSizeValue;

            StringBuilder resultBuilder = new StringBuilder(row * col);

            // 遍历每个色块，读取颜色并映射回字符
            for (int i = 0; i < row; i++)
            {
                for (int j = 0; j < col; j++)
                {
                    // 计算当前色块在Mat中的位置
                    int startX = i * partSizeValue;
                    int endX = (i + 1) * partSizeValue;
                    int startY = j * partSizeValue;
                    int endY = (j + 1) * partSizeValue;

                    // 获取色块区域
                    Mat block = mat[new Range(startY, endY), new Range(startX, endX)];

                    // 计算色块的平均颜色
                    Scalar meanScalar = Cv2.Mean(block);
                    Color averageColor = Color.FromArgb(
                        255,
                        (int)meanScalar.Val2, // R
                        (int)meanScalar.Val1, // G  
                        (int)meanScalar.Val0  // B
                    );

                    // 检查是否为透明色，如果是则立即结束
                    if (averageColor.A == 0 || IsTransparentColor(averageColor))
                    {
                        return resultBuilder.ToString();
                    }

                    // 查找对应的字符
                    char character = ' ';
                    if (colorToCharMap.ContainsKey(averageColor))
                    {
                        character = colorToCharMap[averageColor];
                    }
                    else
                    {
                        // 如果找不到精确匹配，尝试寻找最接近的颜色
                        character = FindClosestColorCharacter(averageColor, colorToCharMap);
                    }

                    resultBuilder.Append(character);
                }
            }

            return resultBuilder.ToString();
        }

        /// <summary>
        /// 判断颜色是否为透明色
        /// </summary>
        private static bool IsTransparentColor(Color color)
        {
            // 检查 Alpha 通道是否为 0，或者 RGB 值是否与 Color.Transparent 匹配
            return color.A == 0 ||
                   (color.R == Color.Transparent.R &&
                    color.G == Color.Transparent.G &&
                    color.B == Color.Transparent.B);
        }

        /// <summary>
        /// 寻找最接近颜色的字符（容差匹配）
        /// </summary>
        private static char FindClosestColorCharacter(Color targetColor, Dictionary<Color, char> colorToCharMap)
        {
            char closestChar = ' ';
            double minDistance = double.MaxValue;

            foreach (var kvp in colorToCharMap)
            {
                double distance = ColorDistance(targetColor, kvp.Key);
                if (distance < minDistance)
                {
                    minDistance = distance;
                    closestChar = kvp.Value;
                }
            }

            return closestChar;
        }

        /// <summary>
        /// 计算两个颜色之间的欧几里得距离
        /// </summary>
        private static double ColorDistance(Color color1, Color color2)
        {
            int rDiff = color1.R - color2.R;
            int gDiff = color1.G - color2.G;
            int bDiff = color1.B - color2.B;

            return Math.Sqrt(rDiff * rDiff + gDiff * gDiff + bDiff * bDiff);
        }
    }
}
